package cn.com.connext.scrm.service;

import cn.com.connext.scrm.config.Constants;
import cn.com.connext.scrm.domain.master.Product;
import cn.com.connext.scrm.domain.master.ProductStockLogs;
import cn.com.connext.scrm.repository.master.CouponRepository;
import cn.com.connext.scrm.repository.master.ProductRepository;
import cn.com.connext.scrm.repository.master.ProductStockLogsRepository;
import cn.com.connext.scrm.service.dto.CouponCrmDTO;
import cn.com.connext.scrm.service.dto.JsonResult;
import cn.com.connext.scrm.service.mapper.ProductService;
import cn.com.connext.scrm.utils.EntityUtils;
import cn.com.connext.scrm.web.rest.req.*;
import cn.com.connext.scrm.web.rest.resp.ProductResp;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import javafx.scene.canvas.CanvasBuilder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.persistence.criteria.Predicate;
import javax.persistence.metamodel.EntityType;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl implements ProductService {
    private final static Logger log = LoggerFactory.getLogger(ProductService.class);

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private CouponRepository couponRepository;

    private RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private AccessTokenImpl accessTokenImpl;

    @Autowired
    private ProductStockLogsRepository productStockLogsRepository;


    @Override
    public JsonResult save(ProductReq req) {
        JsonResult jsonResult = new JsonResult();
        //前台改为可选多个会员等级 后台对应产生多条数据
        String level = req.getLevel();
        String[] split = level.split(",");
        for (String item : split) {
            Product product = new Product();
            BeanUtils.copyProperties(req, product);
            product.setLevel(item);
            if (req.getType() != null && req.getType().compareTo(2) == 0) {
                List<CouponCrmDTO> couponCrmDTOS = couponList();
                Map<String, CouponCrmDTO> map = couponCrmDTOS.stream().collect(Collectors.toMap(CouponCrmDTO::getCouponId, c -> c));
                CouponCrmDTO couponCrmDTO = map.get(req.getCouponId());
                log.info("map={}", map);
                log.info("-----------------couponCrmDTO={}", JSON.toJSONString(couponCrmDTO));
                if (null == couponCrmDTO) {
                    jsonResult.setState(1);
                    jsonResult.setMessage("优惠卷异常，请联系管理员");
                    return jsonResult;
                }
                if (couponCrmDTO.getStore().compareTo(1) < 0) {
                    jsonResult.setState(1);
                    jsonResult.setMessage("优惠卷库存不足");
                    return jsonResult;
                };
                product.setStock(couponCrmDTO.getStore());
            }else {
                product.setStock(req.getStock()==null ?0 :req.getStock());
            }
            if (StringUtils.isEmpty(req.getId())) {
                product.setCreateTime(new Date());
            }
            product.setIsDelete(0);
            product.setIsAlive(0);//是否上架  1上架 0下架
            product.setLimitPerperson(req.getLimitPerperson());
            product.setLimitType(req.getLimitType());
            product.setUpdateTime(new Date());
            Product result = productRepository.saveAndFlush(product);
            jsonResult.setData(result);
        }
        //可能会产生多条 返回值前台没用 暂时注释掉了
         //jsonResult.setState(0);
        return jsonResult;
    }


    @Override
    public Page queryLists(ProduceQueryReq req) {
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Date now = new Date();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "level"));
        Specification<Product> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //上架
            list.add(criteriaBuilder.equal(root.get("isAlive"), 1));
            list.add(criteriaBuilder.notEqual(root.get("stock"), 0));
            //未删除
            list.add(criteriaBuilder.equal(root.get("isDelete"), 0));
            list.add(criteriaBuilder.isNotNull(root.get("onlineTime")));
            list.add(criteriaBuilder.isNotNull(root.get("offlineTime")));

            list.add(criteriaBuilder.lessThan(root.get("onlineTime"), now));
            list.add(criteriaBuilder.greaterThan(root.get("offlineTime"), now));

            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };

        Page page = productRepository.findAll(specification, pageable);
        List<Product> products = page.getContent();
        List<ProductResp> productRespList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(products)) {
            productRespList = EntityUtils.dtoList2PojoList(products, ProductResp.class);
            //productRespList = productRespList.stream().filter(c->c.getOfflineTime()!=null &&c.getOnlineTime()!=null).filter(c -> c.getOnlineTime().before(new Date()) && c.getOfflineTime().after(new Date())).collect(Collectors.toList());
        }
        return new PageImpl<>(productRespList, pageable, page.getTotalElements());
    }

    @Override
    public Page pages(ProduceQueryReq req) {
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "createTime"));
        Specification<Product> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //等级查询
            if (StringUtils.isNotBlank(req.getLevel())) {
                list.add(criteriaBuilder.equal(root.get("level"), req.getLevel()));
            }
            //是否上架
            if (null != req.getIsAlive()) {
                list.add(criteriaBuilder.equal(root.get("isAlive"), req.getIsAlive()));
            }

            //所属积分商城
            if (null != req.getPointManagerId()) {
                list.add(criteriaBuilder.equal(root.get("pointManagerId"), req.getPointManagerId()));
            }

            //产品名称
            if (StringUtils.isNotBlank(req.getName())) {
                list.add(criteriaBuilder.like(root.get("name"), "%" + req.getName() + "%"));
            }
            list.add(criteriaBuilder.equal(root.get("isDelete"), 0));//未删除
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };

        Page page = productRepository.findAll(specification, pageable);
        List<Product> products = page.getContent();
        List<ProductResp> productRespList = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(products)) {
            productRespList = EntityUtils.dtoList2PojoList(products, ProductResp.class);
        }
        return new PageImpl<>(productRespList, pageable, page.getTotalElements());
    }

    @Override
    public JsonResult delete(String id) {
        JsonResult jsonResult = new JsonResult();
        Product product = productRepository.findOne(id);
        product.setIsDelete(1);
        product.setUpdateTime(new Date());
        product = productRepository.saveAndFlush(product);
        jsonResult.setState(0);
        jsonResult.setData(product);
        jsonResult.setMessage("删除成功");
        return jsonResult;
    }

    @Override
    public JsonResult isAlive(String id) {
        Product product = productRepository.findOne(id);
        // 是否上架  1上架 0下架
        Integer isAlive = product.getIsAlive();
        if (isAlive.compareTo(1) == 0) {
            product.setIsAlive(0);
        } else {
            product.setIsAlive(1);
        }
        // 获取库存数量
        if ( product.getStock() > 0 || product.getStock() == 0){
            product.setStock(product.getStock());
        }
        product.setUpdateTime(new Date());
        product = productRepository.saveAndFlush(product);
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(0);
        jsonResult.setData(product);
        return jsonResult;
    }

    @Override
    public JsonResult stock(StockReq req) {
        JsonResult jsonResult = new JsonResult();
        Product product = productRepository.findOne(req.getId());
        //库存0增加  1减少
        if (req.getStockType().compareTo(0) == 0) {
            Integer stock = req.getStock() + product.getStock();
            Integer count = productRepository.updateStock(stock, product.getStock(), req.getId());
            if (count.compareTo(1)>=0){
                //记录库存更新记录
                ProductStockLogs productStockLogs = new ProductStockLogs();
                productStockLogs.setCreateTime(new Date());
                productStockLogs.setStockType(req.getStockType());
                productStockLogs.setStock(req.getStock());
                productStockLogs.setProductId(req.getId());
                productStockLogsRepository.saveAndFlush(productStockLogs);
            }
            jsonResult.setState(0);
            return jsonResult;
        }
        if (req.getStock().compareTo(product.getStock()) > 0) {
            jsonResult.setState(1);
            jsonResult.setMessage("库存减少量不能大于库存量");
            return jsonResult;
        }
        Integer stock = product.getStock() - req.getStock();
        Integer countUpdate = productRepository.updateStock(stock, product.getStock(), req.getId());

        if (countUpdate.compareTo(1)>=0){
            //记录库存更新记录
            ProductStockLogs productStockLogs = new ProductStockLogs();
            productStockLogs.setCreateTime(new Date());
            productStockLogs.setStockType(req.getStockType());
            productStockLogs.setStock(req.getStock());
            productStockLogs.setProductId(req.getId());
            productStockLogsRepository.saveAndFlush(productStockLogs);
        }
        jsonResult.setState(0);
        return jsonResult;
    }

    @Override
    public JsonResult detail(String req) {
        JsonResult jsonResult = new JsonResult();
        ProductResp productResp = new ProductResp();
        Product product = productRepository.findOne(req);
        if (null != product) {
            //增加 2021-12-21 前端只需要拿到最低的等级
            String level = product.getLevel();
            String[] split = level.split(",");
            Arrays.sort(split);
            product.setLevel(split[0]);
            // end -------
            BeanUtils.copyProperties(product, productResp);
        }
        jsonResult.setData(productResp);
        jsonResult.setState(0);
        return jsonResult;
    }

    @Override
    public JsonResult getStockLogs(StockLogsReq req) {
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "createTime"));
        Specification<ProductStockLogs> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (StringUtils.isNotBlank(req.getId())) {
                list.add(criteriaBuilder.equal(root.get("productId"), req.getId()));
            }
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };
        Page page = productStockLogsRepository.findAll(specification, pageable);
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(0);
        jsonResult.setData(page);
        return jsonResult;
    }

    @Override
    public Page findByPointManagerId(ProduceReq req) {
//        List<Product>  products = productRepository.findByPointManagerId(req.getPointManagerId());
//        List<ProductResp> productRespList = new ArrayList<>();
//        if (CollectionUtils.isNotEmpty(products)) {
//            productRespList = EntityUtils.dtoList2PojoList(products, ProductResp.class);
//            //    productRespList = productRespList.stream().filter(
//            c->c.getOfflineTime()!=null &&c.getOnlineTime()!=null).filter(
//            c -> c.getOnlineTime().before(new Date()) && c.getOfflineTime().after(new Date())).collect(Collectors.toList());
//        }
//        return productRespList;
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();

        Date now = new Date();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "level"));

        Specification<Product> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //上架
            list.add(criteriaBuilder.equal(root.get("isAlive"), 1));
            //list.add(criteriaBuilder.notEqual(root.get("stock"),  0));
            list.add(criteriaBuilder.isNotNull(root.get("stock")));
            //未删除
            list.add(criteriaBuilder.equal(root.get("isDelete"), 0));
            list.add(criteriaBuilder.isNotNull(root.get("onlineTime")));
            list.add(criteriaBuilder.isNotNull(root.get("offlineTime")));
            list.add(criteriaBuilder.equal(root.get("pointManagerId"), req.getPointManagerId()));

            list.add(criteriaBuilder.lessThan(root.get("onlineTime"), now));
            list.add(criteriaBuilder.greaterThan(root.get("offlineTime"), now));
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };

        Page page = productRepository.findAll(specification, pageable);
        List<Product> products = page.getContent();
        List<ProductResp> productRespList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(products)) {
            productRespList = EntityUtils.dtoList2PojoList(products, ProductResp.class);
            productRespList = productRespList.stream().filter(c->c.getOfflineTime()!=null &&c.getOnlineTime()!=null).filter(c -> c.getOnlineTime().before(new Date()) && c.getOfflineTime().after(new Date())).collect(Collectors.toList());
            //默认积分商城显示需要去重
            List<Product>  productList = productRepository.findByPointManagerId(req.getPointManagerId());

            if (1==req.getPointManagerId()) {
                //添加过滤数组类型
                productRespList.stream().forEach(productResp -> productResp.setGroupStr(
                    productResp.getPointManagerName()+productResp.getName()+productResp.getPoints()));
                Map<String,List<ProductResp>> map = new HashMap<>();
                productRespList.stream().collect(Collectors.groupingBy(ProductResp::getGroupStr,Collectors.toList())).forEach(map::put);
                //情空数据
                productRespList.clear();
                log.info("分组后信息为",JSON.toJSONString(map));

                List<ProductResp> productRespLists = new ArrayList<>();
                map.forEach((s, productResps) -> {
                    //排序 按照会员等级从大到小
                    List<ProductResp> collect = productResps.stream().sorted(Comparator.comparing(ProductResp::getLevel)).collect(Collectors.toList());
                    ProductResp productResp = productResps.get(0);

                    String level = productResps.stream().map(ProductResp::getLevel).collect(Collectors.joining(","));
                    if (!level.contains(",") || StringUtils.isBlank(level)){
                        productResp.setLevel("1");
                    }else {
                        productResp.setLevel(level.substring(level.length()-1));
                    }

                    productResp.setGroupLists(JSON.parseArray(JSON.toJSONString(collect),JSONObject.class));
                    productRespLists.add(productResp);
                });
                log.info("分组排序后数据"+JSON.toJSONString(productRespLists));
                //添加默认商城排序规则
                List<ProductResp> collect = productRespLists.stream().sorted(Comparator.comparing(ProductResp::getProductType,Comparator.nullsLast(Integer::compareTo))
                    .thenComparing(ProductResp::getPoints,Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
                //productRespLists.sort(Comparator.comparing(ProductResp::getProductType));
                log.info("按照type类型与积分排序后数据"+JSON.toJSONString(collect));
                productRespList.addAll(collect);
            }

        }

       return new PageImpl<>(productRespList, pageable, page.getTotalElements());
    }

    @Override
    public Product getProductDetails(String productId) {
        return productRepository.findOne(productId);
    }

    private List<CouponCrmDTO> couponList() {
        String accessToken = accessTokenImpl.getAccessToken();
        String requestUrl = Constants.CouponList.replace("ACCESSTOKEN", accessToken);
        String result = restTemplate.getForEntity(requestUrl, String.class).getBody();
        Object rows = JSON.parseObject(result, Map.class).get("rows");
        List<CouponCrmDTO> couponCrmDTOS = JSONObject.parseArray(JSON.toJSONString(rows), CouponCrmDTO.class);
        log.info("获取crm优惠卷列表couponCrmDTOS={}", JSON.toJSONString(couponCrmDTOS));
        return couponCrmDTOS;
    }
}
